home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.92 / crossfir / crossfire-0.92.5 / server / hiscore.c < prev    next >
C/C++ Source or Header  |  1996-07-24  |  10KB  |  323 lines

  1. /*
  2.  * static char *rcsid_hiscore_c =
  3.  *   "$Id: hiscore.c,v 1.13 1995/04/15 04:54:15 master Exp $";
  4.  */
  5.  
  6. /*
  7.     CrossFire, A Multiplayer game for X-windows
  8.  
  9.     Copyright (C) 1992 Frank Tore Johansen
  10.  
  11.     This program is free software; you can redistribute it and/or modify
  12.     it under the terms of the GNU General Public License as published by
  13.     the Free Software Foundation; either version 2 of the License, or
  14.     (at your option) any later version.
  15.  
  16.     This program is distributed in the hope that it will be useful,
  17.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.     GNU General Public License for more details.
  20.  
  21.     You should have received a copy of the GNU General Public License
  22.     along with this program; if not, write to the Free Software
  23.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  
  25.     The author can be reached via e-mail to frankj@ifi.uio.no.
  26. */
  27.  
  28. #include <global.h>
  29. #ifndef __CEXTRACT__
  30. #include <sproto.h>
  31. #endif
  32.  
  33. /*
  34.  * spool works mostly like strtok(char *, ":"), but it can also
  35.  * log a specified error message if something goes wrong.
  36.  */
  37.  
  38. char *spool(char *bp,char *error) {
  39.   static char *prev_pos = NULL;
  40.   char *next_pos;
  41.   if (bp == NULL) {
  42.     if (prev_pos == NULL) {
  43.       LOG(llevError, "Called spool (%s) with NULL without previous call.\n",
  44.           error);
  45.       return NULL;
  46.     }
  47.     bp = prev_pos;
  48.   }
  49.   if (*bp == '\0') {
  50.     LOG(llevError, "spool: End of line at %s\n", error);
  51.     return NULL;
  52.   }
  53.   if ((next_pos = strchr(bp, ':')) != NULL) {
  54.     *next_pos = '\0';
  55.     prev_pos = next_pos + 1;
  56.   } else
  57.     prev_pos = NULL;
  58.   return bp;
  59. }
  60.  
  61. /*
  62.  * Does what it says, copies the contents of the first score structure
  63.  * to the second one.
  64.  */
  65.  
  66. void copy_score(score *sc1,score *sc2) {
  67.   strncpy(sc2->name, sc1->name, BIG_NAME);
  68.   sc2->name[BIG_NAME - 1] = '\0';
  69.   strncpy(sc2->killer, sc1->killer, BIG_NAME);
  70.   sc2->killer[BIG_NAME - 1] = '\0';
  71.   sc2->exp = sc1->exp;
  72.   strcpy(sc2->maplevel,sc1->maplevel);
  73.   sc2->maxhp = sc1->maxhp;
  74.   sc2->maxsp = sc1->maxsp;
  75. }
  76.  
  77. /*
  78.  * Writes the given score structure to a static buffer, and returns
  79.  * a pointer to it.
  80.  */
  81.  
  82. char *put_score(score *sc) {
  83.   static char buf[MAX_BUF];
  84.   sprintf(buf,"%s:%ld:%s:%s:%d:%d",sc->name,sc->exp,sc->killer,sc->maplevel,
  85.           sc->maxhp,sc->maxsp);
  86.   return buf;
  87. }
  88.  
  89. /*
  90.  * The oposite of put_score, get_score reads from the given buffer into
  91.  * a static score structure, and returns a pointer to it.
  92.  */
  93.  
  94. score *get_score(char *bp) {
  95.   static score sc;
  96.   char *cp;
  97.  
  98.   if((cp=strchr(bp,'\n'))!=NULL)
  99.     *cp='\0';
  100.  
  101.   if ((cp = spool(bp, "name")) == NULL)
  102.     return NULL;
  103.   strncpy(sc.name,cp,BIG_NAME);
  104.   sc.name[BIG_NAME - 1] = '\0';
  105.   if ((cp = spool(NULL, "score")) == NULL)
  106.     return NULL;
  107.   sscanf(cp,"%ld",&sc.exp);
  108.   if ((cp = spool(NULL, "killer")) == NULL)
  109.     return NULL;
  110.   strncpy(sc.killer, cp, BIG_NAME);
  111.   sc.killer[BIG_NAME - 1] = '\0';
  112.   if ((cp = spool(NULL, "map")) == NULL)
  113.     return NULL;
  114.   strncpy(sc.maplevel, cp, BIG_NAME);
  115.   sc.maplevel[BIG_NAME - 1] = '\0';
  116.   if ((cp = spool(NULL, "maxhp")) == NULL)
  117.     return NULL;
  118.   sscanf(cp, "%d", &sc.maxhp);
  119.   if ((cp = spool(NULL, "maxhp")) == NULL)
  120.     return NULL;
  121.   sscanf(cp, "%d", &sc.maxsp);
  122.   return ≻
  123. }
  124.  
  125. /*
  126.  * add_score() adds the given score-structure to the high-score list, but
  127.  * only if it was good enough to deserve a place.
  128.  */
  129.  
  130. score *add_score(score *new_score) {
  131.   FILE *fp;
  132.   static score old_score;
  133.   score *tmp_score,pscore[HIGHSCORE_LENGTH];
  134.   char buf[MAX_BUF], filename[MAX_BUF], *bp;
  135.   int nrofscores=0,flag=0,i,comp;
  136.  
  137.   new_score->position=HIGHSCORE_LENGTH+1;
  138.   old_score.position= -1;
  139.   sprintf(filename,"%s/%s",LibDir,HIGHSCORE);
  140.   if((fp=open_and_uncompress(filename,1,&comp))!=NULL) {
  141.     while(fgets(buf,MAX_BUF,fp)!=NULL&&nrofscores<HIGHSCORE_LENGTH) {
  142.       if((tmp_score=get_score(buf))==NULL) break;
  143.       if(!flag&&new_score->exp>=tmp_score->exp) {
  144.         copy_score(new_score,&pscore[nrofscores]);
  145.         new_score->position=nrofscores;
  146.         flag=1;
  147.         if(++nrofscores>=HIGHSCORE_LENGTH)
  148.           break;
  149.       }
  150.       if(!strcmp(new_score->name,tmp_score->name)) { /* Another entry */
  151.         copy_score(tmp_score,&old_score);
  152.         old_score.position=nrofscores;
  153.         if(flag)
  154.           continue;
  155.       }
  156.       copy_score(tmp_score,&pscore[nrofscores++]);
  157.     }
  158.     close_and_delete(fp, comp);
  159.   }
  160.   if(old_score.position!=-1&&old_score.exp>=new_score->exp)
  161.     return &old_score; /* Did not beat old score */
  162.   if(!flag&&nrofscores<HIGHSCORE_LENGTH)
  163.     copy_score(new_score,&pscore[nrofscores++]);
  164.   if((fp=fopen(filename,"w"))==NULL) {
  165.     perror("Couldn't write to highscore-list.\n");
  166.     return NULL;
  167.   }
  168.   for(i=0;i<nrofscores;i++) {
  169.     bp=put_score(&pscore[i]);
  170.     fprintf(fp,"%s\n",bp);
  171.   }
  172.   fclose(fp);
  173.   if(flag) {
  174. /* Eneq(@csd.uu.se): Patch to fix error in adding a new score to the
  175.    hiscore-list */
  176.     if(old_score.position==-1)
  177.       return new_score;
  178.     return &old_score;
  179.   }
  180.   new_score->position= -1;
  181.   if(old_score.position!=-1)
  182.     return &old_score;
  183.   if(nrofscores) {
  184.     copy_score(&pscore[nrofscores-1],&old_score);
  185.     return &old_score;
  186.   }
  187.   LOG(llevError,"Highscore error.\n");
  188.   return NULL;
  189. }
  190.  
  191. void check_score(object *op) {
  192.   char buf[MAX_BUF];
  193.   score new_score;
  194.   score *old_score;
  195.   if(op->stats.exp==0)
  196.     return;
  197.   if(!op->contr->name_changed) {
  198.     if(op->stats.exp>0) {
  199.       new_draw_info(NDI_UNIQUE, 0,op,"As you haven't changed your name, you won't");
  200.       new_draw_info(NDI_UNIQUE, 0,op,"get into the high-score list.");
  201.     }
  202.     return;
  203.   }
  204.   if(QUERY_FLAG(op,FLAG_WAS_WIZ)) {
  205.     new_draw_info(NDI_UNIQUE, 0,op,"Since you have been in wizard mode,");
  206.     new_draw_info(NDI_UNIQUE, 0,op,"you can't enter the high-score list.");
  207.     return;
  208.   }
  209. #ifdef EXPLORE_MODE
  210.   if (op->contr->explore) {
  211.     new_draw_info(NDI_UNIQUE, 0,op,"Since you were in explore mode,");
  212.     new_draw_info(NDI_UNIQUE, 0,op,"you can't enter the high-score list.");
  213.     return;
  214.   }
  215. #endif
  216.   sprintf(buf,"%s the %s",op->name,op->contr->title);
  217.   strncpy(new_score.name,buf,BIG_NAME);
  218.   strncpy(new_score.killer,op->contr->killer,BIG_NAME);
  219.   if(new_score.killer[0]=='\0')
  220.     strcpy(new_score.killer,"a dungeon collapse");
  221.   new_score.exp=op->stats.exp;
  222.   if(op->map == NULL)
  223.     *new_score.maplevel = '\0';
  224.   else { 
  225.     strncpy(new_score.maplevel,op->map->map_object->name,BIG_NAME-1);
  226.     new_score.maplevel[BIG_NAME-1] = '\0';
  227.   }
  228.   new_score.maxhp=(int) op->stats.maxhp;
  229.   new_score.maxsp=(int) op->stats.maxsp;
  230.   if((old_score=add_score(&new_score))==NULL) {
  231.     new_draw_info(NDI_UNIQUE, 0,op,"Error in the highscore list.");
  232.     return;
  233.   }
  234.   if(new_score.position == -1) {
  235.     new_score.position = HIGHSCORE_LENGTH+1; /* Not strictly correct... */
  236.     if(!strcmp(old_score->name,new_score.name))
  237.       new_draw_info(NDI_UNIQUE, 0,op,"You didn't beat your last highscore:");
  238.     else
  239.       new_draw_info(NDI_UNIQUE, 0,op,"You didn't enter the highscore list:");
  240.     draw_one_high_score(old_score);
  241.     new_draw_info(NDI_UNIQUE, 0,op,errmsg);
  242.     draw_one_high_score(&new_score);
  243.     new_draw_info(NDI_UNIQUE, 0,op,errmsg);
  244.     return;
  245.   }
  246.   if(old_score->exp>=new_score.exp)
  247.     new_draw_info(NDI_UNIQUE, 0,op,"You didn't beat your last score:");
  248.   else
  249.     new_draw_info(NDI_UNIQUE, 0,op,"You beat your last score:");
  250.   draw_one_high_score(old_score);
  251.   new_draw_info(NDI_UNIQUE, 0,op,errmsg);
  252.   draw_one_high_score(&new_score);
  253.   new_draw_info(NDI_UNIQUE, 0,op,errmsg);
  254. }
  255.  
  256. void draw_one_high_score(score *sc) {
  257.   if(!strncmp(sc->killer,"quit",MAX_NAME))
  258.     sprintf(errmsg,"%3d %10ld %s quit the game on map %s [%d][%d].",
  259.             sc->position,sc->exp,sc->name,sc->maplevel,sc->maxhp,sc->maxsp);
  260.   else if(!strncmp(sc->killer,"left",MAX_NAME))
  261.     sprintf(errmsg,"%3d %10ld %s left the game on map %s [%d][%d].",
  262.             sc->position,sc->exp,sc->name,sc->maplevel,sc->maxhp,sc->maxsp);
  263.   else
  264.     sprintf(errmsg,"%3d %10ld %s was killed by %s on map %s [%d][%d].",
  265.             sc->position,sc->exp,sc->name,sc->killer,sc->maplevel,
  266.             sc->maxhp,sc->maxsp);
  267. }
  268.  
  269.  
  270. void display_high_score(object *op,int max) {
  271.   FILE *fp;
  272.   char buf[MAX_BUF],buf2[MAX_BUF], filename[MAX_BUF], *bp;
  273.   int i=0,j=0,maxchar=(op==NULL?80:INFOCHARS),comp;
  274.   score *sc;
  275.  
  276.   sprintf(filename,"%s/highscore",LibDir);
  277.   if((fp=open_and_uncompress(filename,0,&comp))==NULL) {
  278.     perror("Couldn't open highscore file");
  279.     if(op!=NULL)
  280.       new_draw_info(NDI_UNIQUE, 0,op,"There is no highscore file.");
  281.     return;
  282.   }
  283.   sprintf(buf,"Nr    Score    Who [max hitpoints][max spellpoints]");
  284.   if(op==NULL && active_socket == (sockets *) NULL)
  285.     printf("%s\n",buf);
  286.   else {
  287.     if(op != NULL)
  288.       clear_win_info(op);
  289.     new_draw_info(NDI_UNIQUE, 0,op,buf);
  290.   }
  291.   while(fgets(buf,MAX_BUF,fp)!=NULL) {
  292.     if(j>=HIGHSCORE_LENGTH||i>=(max-1))
  293.       break;
  294.     if((sc=get_score(buf))==NULL)
  295.       break;
  296.     i++,j++;
  297.     sc->position=j;
  298.     draw_one_high_score(sc);
  299.     strncpy(buf,errmsg,MAX_BUF);
  300.     bp=buf+maxchar;
  301.     if((int)strlen(buf) > maxchar)
  302.       while(*bp!=' '&&bp>buf)
  303.         bp--;
  304.     strncpy(buf2,buf,bp-buf);
  305.     buf2[bp-buf]='\0';
  306.     if (op == NULL && active_socket == (sockets *) NULL)
  307.       printf("%s\n",buf2);
  308.     else
  309.       new_draw_info(NDI_UNIQUE, 0,op,buf2);
  310.  
  311.     if((int)strlen(buf) > maxchar) {
  312.       i++;
  313.       strcpy(buf2,"            ");
  314.       strcat(buf2,bp);
  315.       if(op == NULL && active_socket == (sockets *) NULL)
  316.         printf("%s\n",buf2);
  317.       else
  318.         new_draw_info(NDI_UNIQUE, 0,op,buf2);
  319.     }
  320.   }
  321.   close_and_delete(fp, comp);
  322. }
  323.